package com.cea.papyrus.diagram.sequence.sedi.model.command;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Interaction;

import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.sequence.sedi.edit.SeDiViewFactory;
import com.cea.papyrus.diagram.sequence.sedi.model.util.ModelUtil;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;

public class CreateGraphicalElementCommand extends Command {

    private Element element;
    private GraphElement parentGE;
    private EditPart anyEditPart;
    private GraphElement view;
    private EditPart diagramEditPart;

    // in case of GraphEdge.
    private GraphElement source;
    private GraphElement target;

    @Override
    public void execute() {
        view = SeDiViewFactory.createView(parentGE, element, anyEditPart);
        GraphElement diagram = LookForElement.getDiagram(view);
        diagramEditPart = (EditPart) anyEditPart.getViewer().getEditPartRegistry().get(diagram);
        refresh();
    }

    public void setElement(Element element) {
        this.element = element;
    }

    public void setParentGE(GraphElement parentGE) {
        this.parentGE = parentGE;
    }

    public void setAnyEditPart(EditPart anyEditPart) {
        this.anyEditPart = anyEditPart;
    }

    @Override
    public void undo() {
        parentGE.getContained().remove(view);
        if (view instanceof GraphEdge) {
            GraphEdge graphEdge = (GraphEdge) view;
            source = graphEdge.getAnchorSource();
            target = graphEdge.getAnchorTarget();
            graphEdge.getAnchorSource().getAnchorage().remove(graphEdge.getAnchor().get(0));
            graphEdge.getAnchorTarget().getAnchorage().remove(graphEdge.getAnchor().get(1));
        }
        refresh();
    }

    @Override
    public void redo() {
        parentGE.getContained().add(view);
        if (view instanceof GraphEdge) {
            GraphEdge graphEdge = (GraphEdge) view;
            source.getAnchorage().add(graphEdge.getAnchor().get(0));
            target.getAnchorage().add(graphEdge.getAnchor().get(1));
        }
        refresh();
    }

    @Override
    public boolean canUndo() {
        return super.canUndo() && parentGE != null;
    }

    private void refresh() {
        diagramEditPart.refresh();
        GraphElement element = view;
        while (!(ModelUtil.getSemantic(element) instanceof Interaction) && element != null) {
            element = element.getContainer();
        }
        if (element != null) {
            EditPart interactionEditPart =
                    (EditPart) diagramEditPart.getViewer().getEditPartRegistry().get(
                            ModelUtil.getGraphElement(ModelUtil.<Element> getSemantic(element),
                                    (GraphElement) diagramEditPart.getModel()));
            if (interactionEditPart != null) {
                interactionEditPart.refresh();
            }
        }
    }

}
